#include "NetworkModule.h"
#include <string>
#include <ut_debug.h>
#include <common.h>
#include <xml.h>
#include "SessionMgr.h"
#include "PipeManager.h"

using namespace std;
using namespace utility::system;
using namespace utility::xml;

#pragma comment(lib, "net_module.lib")
#pragma comment(lib, "pipe_module.lib")
#pragma comment(lib, "system.lib")
#pragma comment(lib, "strutil.lib")

CNetworkModule::CNetworkModule(void)
{
    m_pNetModule = get_net_module();
    m_pPipeModule = get_pipe_module();
}


CNetworkModule::~CNetworkModule(void)
{
    destroy_net_module();
    destroy_pipe_module();
}

bool CNetworkModule::Init()
{
    string strConfigFile = utility::system::get_exe_path();
    strConfigFile += "/NetworkConfig.xml";
    if (!_LoadConfig(strConfigFile.c_str()))
    {
        LOG(CRITICAL) << "Failed on loading network configuration: " << strConfigFile;
        return false;
    }

    if (!m_strPort.empty())
    {
        try
        {
            m_pListener = m_pNetModule->create_listener();
            m_pListener->set_session_mgr(CSessionMgr::Instance());
            m_pListener->enable_secure_layer();
            string strCurrentDir = utility::system::get_exe_path();
            strCurrentDir += '/';
            m_pListener->set_certificate_chain_file((strCurrentDir + m_strCrtChainFile).c_str());
            m_pListener->set_password(m_strPwd.c_str());
            m_pListener->set_private_key_file((strCurrentDir + m_strKeyFile).c_str());
            m_pListener->set_dh_file((strCurrentDir + m_strDhFile).c_str());
            if (!m_pListener->start(m_strIP.c_str() ,m_strPort.c_str()))
            {
                LOG(CRITICAL) << "Failed to listen IP:" << m_strIP << " ,port:" << m_strPort;
                return false;
            }
        }
        catch(...)
        {
            return false;
        }

    }

    string strPipeConfigFile = utility::system::get_exe_path();
    strPipeConfigFile += "/LGPipeConfig.xml";
    if (!m_pPipeModule->initialize(strPipeConfigFile.c_str(), CPipeManager::Instance(), m_pNetModule))
    {
        LOG(CRITICAL) << "Failed on initializing pipe module";
        return false;
    }

    return true;
}

bool CNetworkModule::_LoadConfig( const char * szFileName )
{
    CMarkupSTL xmlDoc;
    if (!xmlDoc.Load(szFileName))
    {
        LOG(CRITICAL) << "Failed on open configuration file: " << szFileName << " Error:" << xmlDoc.GetError();
        return false;
    }

    if (!xmlDoc.FindElem("root"))
    {
        LOG(CRITICAL) << "Failed to find XML node: root";
        return false;
    }
    xmlDoc.IntoElem();

    if (xmlDoc.FindElem("network"))
    {
        m_strPort = xmlDoc.GetAttrib("listen_port");
        if (m_strPort.length() == 0)
        {
            LOG(CRITICAL) << "Failed to find XML attribution: network.listen_port";
            return false;
        }

        m_strIP = xmlDoc.GetAttrib("ip_address");
        if (m_strIP.length() == 0)
        {
            LOG(CRITICAL) << "Failed to find XML attribution: network.ip_address";
            return false;
        }

        m_strCrtChainFile = xmlDoc.GetAttrib("certificate_chain_file");
        if (m_strCrtChainFile.length() == 0)
        {
            LOG(CRITICAL) << "Failed to get XML attr: certificate_chain_file";
            return false;
        }

        m_strKeyFile = xmlDoc.GetAttrib("key_file");
        if (m_strKeyFile.length() == 0)
        {
            LOG(CRITICAL) << "Failed to get XML attr: key_file";
            return false;
        }

        m_strDhFile = xmlDoc.GetAttrib("dh_file");
        if (m_strDhFile.length() == 0)
        {
            LOG(CRITICAL) << "Failed to get XML attr : dh_file";
            return false;
        }

        m_strPwd = xmlDoc.GetAttrib("pwd");
        if (m_strPwd.length() == 0)
        {
            LOG(CRITICAL) << "Failed to get XML attr : pwd";
            return false;
        }

        return true;
    }

    return false;
}

bool CNetworkModule::Run()
{
    if (m_pNetModule)
        return m_pNetModule->run() > 0;
    return false;
}
